namespace FineUtil.PaperGeo
{

    /// <summary>
    /// Point.
    /// </summary>
    public struct GeoPoint
    {

        /// <summary>
        /// X-coordinate.
        /// </summary>
        public int X;

        
        /// <summary>
        /// Y-coordinate.
        /// </summary>
        public int Y;
        
        
        /// <summary>
        /// Trivial constructor.
        /// </summary>
        /// <param name="x">X-coordinate.</param>
        /// <param name="y">Y-coordinate.</param>
        public GeoPoint(int x, int y)
        {
            this.X = x;
            this.Y = y;
        }


        /// <summary>
        /// Makes a rectangle from a point and a size.
        /// </summary>
        /// <param name="point">left top point.</param>
        /// <param name="size">size.</param>
        /// <returns></returns>
        public static GeoRect operator * (GeoPoint point, GeoSize size)
        {
            return new GeoRect(point, size);
        }


        /// <summary>
        /// Shifts the point with a delta.
        /// </summary>
        /// <param name="p">the origin point.</param>
        /// <param name="d">the detat to shift.</param>
        /// <returns>new point.</returns>
        public static GeoPoint operator + (GeoPoint p, GeoSize d)
        {
            return new GeoPoint(p.X + d.W, p.Y - d.H);
        }


        /// <summary>
        /// Determines a delta between two pointes.
        /// </summary>
        /// <param name="p1">the first point.</param>
        /// <param name="p2">the sceond point.</param>
        /// <returns>delta.</returns>
        public static GeoSize operator - (GeoPoint p1, GeoPoint p2)
        {
            return new GeoSize(p1.X - p2.X, p1.Y - p2.Y);
        }



        
        public override string ToString()
        {
            return "(" + X + "," + Y + ")";
        }

        public bool Equals(GeoPoint p2)
        {
            return this.X == p2.X
                && this.Y == p2.Y;
        }

        public override bool Equals(object obj)
        {
            return Equals((GeoPoint) obj);
        }
        
        public static bool operator == (GeoPoint p1, GeoPoint p2)
        {
            return p1.X == p2.X && p1.Y == p2.Y;
        }
        
        public static bool operator != (GeoPoint p1, GeoPoint p2)
        {
            return p1.X != p2.X || p1.Y != p2.Y;
        }
        

        public override int GetHashCode()
        {
            return (X*7 + Y*11 + (X ^ Y)) & 0x7FFFFFFF;
        }
    }


}
